package com.settlement.system.csv;

import com.settlement.system.common.enums.ExcelFileType;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;


/**
 * @author author
 */
@Slf4j
public class CsvExportBuilder {
    /**
     * 单文件（CSV或XLSX） 不压缩
     */
    public final static int SINGLE_MODEL = 0;

    /**
     * 多文件（CSV或XLSX），压缩成一个zip包（数据太多，需要分多文件，因为一个文件太大会无法打开）
     */
    public final static int MULTI_ZIP_MODEL = 1;

    /**
     * 多文件（CSV或XLSX），不压缩 (场景：唯品账单导出，由于是多个选项卡一起导出，要求最后才压缩，所以单个里面不能压缩)
     */
    public final static int MULTI_NOT_ZIP_MODEL = 2;

    public final static int MAX_ROWS_NUM = 100*10000;

    private String fileName;
    private Class headClass;
    private int model = SINGLE_MODEL;
    private CsvDatas csvDatas;
    private Integer singleFileRowsNum = 500000;
    private String parentPath;
    private File parentFile;

    private CsvWrite csvWrite;
    private Headers headers;
    private boolean customized = false;
    private boolean ifMapData = false;
    private List<List<String>> xlsxHeaderList;
    Map<Integer, Integer> columnWidthMap;

    private ExcelFileType fileType;

    public CsvExportBuilder fileType(ExcelFileType fileType) {
        this.fileType = fileType;
        return this;
    }

    public CsvExportBuilder xlsxHeaderList(List<List<String>> xlsxHeaderList) {
        this.xlsxHeaderList = xlsxHeaderList;
        return this;
    }

    public CsvExportBuilder customized(boolean customized){
        this.customized = customized;
        return this;
    }

    public CsvExportBuilder ifMapData(boolean ifMapData){
        this.ifMapData = ifMapData;
        return this;
    }

    public CsvExportBuilder fileName(String fileName) {
        this.fileName = fileName;
        return this;
    }

    public CsvExportBuilder columnWidthMap(Map<Integer, Integer> columnWidthMap) {
        this.columnWidthMap = columnWidthMap;
        return this;
    }

    public CsvExportBuilder headClass(Class headClass) {
        this.headClass = headClass;
        return this;
    }

    public CsvExportBuilder model(Integer model) {
        this.model = model;
        return this;
    }

    public CsvExportBuilder singleFileRowsNum(Integer singleFileRowsNum) {
        this.singleFileRowsNum = singleFileRowsNum;
        return this;
    }

    public CsvExportBuilder parentPath(String parentPath) {
        this.parentPath = parentPath;
        return this;
    }

    public CsvExportBuilder csvDatas(CsvDatas csvDatas) {
        this.csvDatas = csvDatas;
        return this;
    }

    public CsvExportBuilder headers(Headers headers){
        this.headers = headers;
        return this;
    }

    private void build() throws Exception {

        if (StringUtils.isEmpty(fileName)) {
            throw new NullPointerException("文件名不能为空");
        }

        if (headClass == null && headers == null && xlsxHeaderList == null) {
            throw new NullPointerException("文件头不能为空");
        }

        if (model != SINGLE_MODEL && model != MULTI_ZIP_MODEL && model != MULTI_NOT_ZIP_MODEL) {
            throw new IllegalArgumentException("model 只能是0,1或者2");
        }

        //默认CSV
        if (fileType == null ) {
            fileType = ExcelFileType.CSV;
        }

        boolean flag = (singleFileRowsNum < 0 || singleFileRowsNum > MAX_ROWS_NUM)
                && (model == MULTI_ZIP_MODEL || model == MULTI_NOT_ZIP_MODEL);
        if (flag) {
            throw new IllegalArgumentException("单个文件的行数不能小于0,大于"+MAX_ROWS_NUM);
        }

        if(!StringUtils.isEmpty(parentPath)){
            parentFile = new File(parentPath);
            if(!parentFile.exists()){
                parentFile.mkdirs();
            }

            fileName = parentPath + fileName;
        }
        // 自定义导出的headers在这之前已经存在，非自定义导出的在此处生成
        if(headers == null && headClass != null){
            headers = HeadParseUtil.parse(headClass);
        }

        if (model == SINGLE_MODEL) {
            csvWrite = new SingleCsvWrite(fileType,
                                        headClass,
                                        headers,
                                        fileName,
                                        customized,
                                        ifMapData,
                                        xlsxHeaderList,
                                        columnWidthMap
                    );
        } else {
            /*csvWrite = new MultiCsvWrite(fileType,
                                        headClass,
                                        headers,
                                        fileName,
                                        singleFileRowsNum,
                                        model,
                                        customized,
                                        ifMapData,
                                        xlsxHeaderList,
                                        columnWidthMap
            );*/
        }

        if (csvDatas != null) {
            csvDatas.pushDatasToCsvWrite(csvWrite);
        }
    }

    /**
     * 导出
     *
     * @param response
     */
    public void export(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("开始准备数据");
        build();
        log.info("数据准备完成");
        File file = csvWrite.getFile();
        csvWrite.close();

        FileInputStream in = null;
        OutputStream out = null;

        try {
            log.info("开始传输数据");
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/x-msdownload");
            response.setHeader("Content-Disposition", "attachment;filename=" + getFileName(request,file.getName()));

            in = new FileInputStream(file);
            out = response.getOutputStream();
            byte[] buf = new byte[4089];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }

        } catch (Exception e) {
            log.error("导出异常", e);
            throw e;
        } finally {
            if (null != in) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (null != out) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            file.delete();

            if(parentFile != null){
                parentFile.delete();
            }
            log.info("传输数据完成");
        }
    }

    /**
     * 生成文件
     */
    public void generateFile() throws Exception {
        log.info("开始准备数据");
        build();
        log.info("数据准备完成");
        File file = csvWrite.getFile();
        csvWrite.close();
        log.info("文件生成完成"+file.getAbsolutePath());
    }

    private String getFileName(HttpServletRequest request,String fileName){
        try {
            fileName = java.net.URLEncoder.encode(fileName,"UTF8");
        } catch (Exception ex){

        }
        return fileName;

    }
}
